using System;

namespace RapidHDL
{
	/// <summary>
	/// Summary description for OrGate.
	/// </summary>
	public class OrGate : TruthTableComponent
	{
		public NodeVector InputNodes;
		public NodeVector OutputNodes;

		int iInputWidth;

		public OrGate(Component poParentComponent, string psName, int piInputWidth) : base (poParentComponent,psName)
		{
			iInputWidth = piInputWidth;
			this.GetTruthTable("OrGate",iInputWidth,1);
			InputNodes = this.CreateNodeVector("In",iInputWidth,NodeFlowType.Sink);
			OutputNodes = this.CreateNodeVector("Out",1,NodeFlowType.Source);
            //StabilizeWithUnstableInputs = true;
        }

		protected override void GenerateTruthTable()
		{
			string sInput;

			this.TruthTable.AddTableEntry("default","1");
			sInput = "";
			sInput = sInput.PadRight(iInputWidth,'0');
			this.TruthTable.AddTableEntry(sInput,"0");

            this.TruthTable.AddTableEntry("default-X*1", "1"); // undefined with any one is always 1
		}

		public override bool TransformStructureToVerilog()
		{
			WriteVerilogLookupTable();
			return true;
		}


		protected override Component TestBuildStructure(Component poTopComponent, string psTestName)
		{
			return new OrGate(poTopComponent,"testOr",3);
		}

		protected override string TestComponent(Clock poClock, Component poTestComponent, string psTestName)
		{
			string sTestId;
			OrGate oOrGate = (OrGate)poTestComponent;

			sTestId = "001 = 1";
			oOrGate.InputNodes[0].NodeState = (NodeState)1;
			oOrGate.InputNodes[1].NodeState = (NodeState)0;
			oOrGate.InputNodes[2].NodeState = (NodeState)0;
			poClock.DoClock(1.0);
			if(oOrGate.OutputNodes[0].NodeState != (NodeState)1)
				return sTestId;

			sTestId = "011 = 1";
			oOrGate.InputNodes[2].NodeState = (NodeState)1;
			poClock.DoClock(1.0);
			if(oOrGate.OutputNodes[0].NodeState != (NodeState)1)
				return sTestId;

			sTestId = "000 = 0";
			oOrGate.InputNodes[0].NodeState = (NodeState)0;
			oOrGate.InputNodes[1].NodeState = (NodeState)0;
			oOrGate.InputNodes[2].NodeState = (NodeState)0;
			this.RapidHardware.Simulation.Clock.DoClock(1.0);
			if(oOrGate.OutputNodes[0].NodeState != (NodeState)0)
				return sTestId;

			sTestId = "x11 = x";
			oOrGate.InputNodes[2].NodeState = NodeState.Undefined;
			poClock.DoClock(1.0);
			if(oOrGate.OutputNodes[0].NodeState != NodeState.Undefined)
				return sTestId;

			return "";
		}
	}
}
